#ifndef STRUCTMESH_IDXTRANSLATION_HPP
#define STRUCTMESH_IDXTRANSLATION_HPP

#include "typeAliases.hpp"

namespace hms {

/**
 * @brief For any edge index within a local mesh partition, returns the index of
 * that same edge within the global mesh according to the provided offset and
 * sizes.
 * 
 * @param idx Edge index within the local mesh partition.
 * @param meshSizeGlobal Size of the global mesh.
 * @param meshSizeLocal Size of the local mesh partition.
 * @param offset Offset of the bottom left domain cell of the local mesh
 * partition relative to the global mesh's bottom left domain cell.
 * @return Index Edge index within the global mesh.
 */
Index edgeLocalToGlobal(
	Index idx,
	const Ref<const Array2i>& meshSizeGlobal,
	const Ref<const Array2i>& meshSizeLocal,
	const Ref<const Array2i>& offset
);

/**
 * @brief For any edge index within the global mesh, returns the index of
 * that same edge within a local mesh partition according to the provided offset
 * and sizes.
 * 
 * @param idx Edge index within the global mesh partition.
 * @param meshSizeGlobal Size of the global mesh.
 * @param meshSizeLocal Size of the local mesh partition.
 * @param offset Offset of the bottom left domain cell of the local mesh
 * partition relative to the global mesh's bottom left domain cell.
 * @return Index Edge index within the local mesh partition.
 */
Index edgeGlobalToLocal(
	Index idx,
	const Ref<const Array2i>& meshSizeGlobal,
	const Ref<const Array2i>& meshSizeLocal,
	const Ref<const Array2i>& offset
);

/**
 * @brief Translates the edge index of a horizontal edge from a local mesh
 * partition to the global mesh by using the provided sizes and offset.
 * 
 * @param idx Edge index within the local mesh partition.
 * @param meshSizeGlobal Size of the global mesh.
 * @param meshSizeLocal Size of the local mesh partition.
 * @param offset Offset of the bottom left domain cell of the local mesh
 * partition relative to the global mesh's bottom left domain cell.
 * @return Index Edge index within the global mesh.
 * 
 * Use these functions starting with 'h' or 'v' if you know that some edges
 * are all either horizontal or vertical. Otherwise, use edgeLocalToGlobal.
 */
Index hEdgeLocalToGlobal(
	Index idx,
	const Ref<const Array2i>& meshSizeGlobal,
	const Ref<const Array2i>& meshSizeLocal,
	const Ref<const Array2i>& offset
);

/**
 * @brief Translates the edge index of a vertical edge from a local mesh
 * partition to the global mesh by using the provided sizes and offset.
 * 
 * @see hEdgeLocalToGlobal
 */
Index vEdgeLocalToGlobal(
	Index idx,
	const Ref<const Array2i>& meshSizeGlobal,
	const Ref<const Array2i>& meshSizeLocal,
	const Ref<const Array2i>& offset
);

/**
 * @brief Translates the edge index of a horizontal edge from the global mesh to
 * a local mesh partition by using the provided sizes and offset.
 * 
 * @see hEdgeLocalToGlobal
 */
Index hEdgeGlobalToLocal(
	Index idx,
	const Ref<const Array2i>& meshSizeGlobal,
	const Ref<const Array2i>& meshSizeLocal,
	const Ref<const Array2i>& offset
);

/**
 * @brief Translates the edge index of a vertical edge from the global mesh to
 * a local mesh partition by using the provided sizes and offset.
 * 
 * @see hEdgeLocalToGlobal
 */
Index vEdgeGlobalToLocal(
	Index idx,
	const Ref<const Array2i>& meshSizeGlobal,
	const Ref<const Array2i>& meshSizeLocal,
	const Ref<const Array2i>& offset
);

}

#endif